using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using EnvDTE;
using EnvDTE80;
using GuidanceExplorer.Config;
using GuidanceExplorer.Controls;
using GuidanceExplorer.Model;
using GuidanceExplorer.Services;
using GuidanceExplorer.Views;
using GuidanceExplorerAddIn.Controls;
using GuidanceExplorerAddIn.Services;
using GuidanceExplorerAddIn.Windows;
using GuidanceExplorerAddIn.Properties;
using System.Drawing;

namespace GuidanceExplorerAddIn
{
    /// <summary>
    /// Acts as a broker between the Guidance Explorer views (tree view, list view and detail view)
    /// </summary>
    partial class GEController
    {
        #region private members

        private const string TreeViewGuid = "{59325CE6-0410-4da9-B2F9-B153417BC096}";

        private IServiceProvider _serviceProvider;
        private IAddinModelStorageService _modelService;
        private IWinFormsRenderService _winFormsRenderService;
        private IHtmlRenderService _htmlRenderService;
        private IOnlineStorageService _onlineStorage;
        private IAsyncLoadLibrariesService _asyncLoadSLibraryService;
        private AddIn _addInInstance;
        private GETreeView _treeView;
        private SolutionEvents _solutionEvents = null;         
        private IList<string> addinOpenedWindows;

        #endregion

        private DTE2 VisualStudio
        {
            get { return this._serviceProvider.GetService<DTE, DTE2>(); }
        }

        public TreeView TreeView
        {
            get { return _treeView.TreeView; }
        }

        /// <summary>
        /// Implements the constructor for the Add-in object. Place your initialization code within this method.
        /// </summary>
        public GEController(IServiceProvider serviceProvider, AddIn addinInstance)
        {
            _onlineStorage = new OnlineStorageService();
            System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenExeConfiguration(Assembly.GetExecutingAssembly().Location);
            OnlineStorageService.OnlineStorageConfigSection = configuration.GetSection("OnlineStorage") as OnlineStorageSection;

            _htmlRenderService = new HtmlRenderService();

            _serviceProvider = serviceProvider;
            _addInInstance = addinInstance;
            //_modelService = Providers.ModelStorageServiceProvider.GetInstance().ModelStorageService;

            _modelService = new AddinModelStorageService();
            _modelService.LoadGuidance(Path.GetDirectoryName(this.GetType().Assembly.Location), ClientFlavour.Offline);
            //_modelService.LoadAddinGuidance(VisualStudio.Solution);

            _winFormsRenderService = new WinFormsRenderService();//new VisualStudioRenderService();
            _htmlRenderService = new HtmlRenderService();
            _asyncLoadSLibraryService = new AsyncLoadLibrariesService();
            _solutionEvents = VisualStudio.Events.SolutionEvents;
            addinOpenedWindows = new List<string>();

            InitCommandHandlers();

            // Subscribe Visual Studio events
            _solutionEvents.Opened += new _dispSolutionEvents_OpenedEventHandler(VisualStudio_Solution_Open);
            //_solutionEvents.BeforeClosing += new _dispSolutionEvents_BeforeClosingEventHandler(VisualStudio_Solution_BeforeClosing);

            if (VisualStudio.Solution.IsOpen)
            {
                LoadAddinGuidance(VisualStudio.Solution);
            }
            //Load libraries
            _asyncLoadSLibraryService.ProcessGuidance(_modelService.Guidance, null);

        }


        public void OnBeginShutdown()
        {
            //Save the changes made to the Guidance tree
            //TODO: check if the guidance is already saved (i.e. when the solution was closed)
            _modelService.SaveGuidance(_modelService.Guidance, Path.GetDirectoryName(GetType().Assembly.Location));
        }

        /// <summary>
        /// Create the root menus for the type provided.
        /// </summary>
        /// <param name="typeWithMenuItemAttributes"></param>
        /// <param name="modelItem"></param>
        /// <returns></returns>
        private List<ToolStripMenuItem> CreateRootMenues(MenuItemAttribute[] menuItemAttributes, IModelItem[] modelItem)
        {
            SortedDictionary<int, MenuItemAttribute> sortedList = new SortedDictionary<int, MenuItemAttribute>();

            //Obtain the attributes and add them to a new list that will be used to sort them.
            foreach (MenuItemAttribute tempAttrib in menuItemAttributes)
            {
                sortedList.Add(tempAttrib.Position, tempAttrib);
            }

            //Keep the root menus to add them later.
            List<ToolStripMenuItem> rootMenus = new List<ToolStripMenuItem>();

            //Get all the attributes of the root guidance.
            foreach (MenuItemAttribute attrib in sortedList.Values)
            {
                //Check the condition for this menu item.
                bool showMenuCondition = false;
                if (attrib.Condition != null)
                {
                    showMenuCondition = attrib.Condition.ShowMenuItem(attrib, modelItem != null ? modelItem[0] : null);
                }
                else
                {
                    showMenuCondition = true;
                }

                //If the attribute condition returns false, then ignore this menu.
                if (!showMenuCondition)
                {
                    continue;
                }

                //Split the menu item hierarchy.
                string[] menuItems = attrib.MenuItemName.Split('\\');

                ToolStripMenuItem menuItem = null;
                //Iterate through each menu item.
                for (int idx = 0; idx < menuItems.Length; idx++)
                {
                    string newMenuName = menuItems[idx];
                    if (menuItem == null)
                    {
                        //Check if there is already a root for this menu.
                        foreach (ToolStripMenuItem tempMenu in rootMenus)
                        {
                            if (tempMenu.Text == newMenuName)
                            {
                                menuItem = tempMenu;
                                break;
                            }
                        }

                        //If the root has not been created
                        if (menuItem == null)
                        {
                            //Create a new menu item.
                            menuItem = new ToolStripMenuItem(newMenuName);
                            LinkMenuItemAttribute linkAtt = attrib as LinkMenuItemAttribute;
                            if (linkAtt != null)
                            {
                                menuItem.Alignment = linkAtt.Alignment;
                                menuItem.ForeColor = linkAtt.ForeColor;
                                menuItem.Font = linkAtt.TextFont;
                            }

                            //Call the method that will populate the menu when it's opened.
                            menuItem.DropDownOpening += new EventHandler(
                                delegate(object sender, EventArgs e)
                                {
                                    PopulateRootMenu(sender as ToolStripDropDownItem);
                                }
                            );

                            //Add the menu to the root list.
                            rootMenus.Add(menuItem);
                        }

                        //Set the command to the menu.
                        if (idx == (menuItems.Length - 1) && //In the last item, create the command.
                            (!string.IsNullOrEmpty(attrib.CommandName))) //There is a command name.
                        {
                            AddCommandInvoker(attrib, menuItem);
                        }
                    }
                    else if (newMenuName == "-")
                    {
                        //If there is a separator, then create it without validating previous existence.
                        menuItem.DropDownItems.Add(new ToolStripSeparator());
                    }
                    else if (menuItem.DropDownItems[newMenuName] != null)
                    {
                        ToolStripMenuItem parent = menuItem;
                        //Check if there is already a menu with this name.
                        menuItem = menuItem.DropDownItems[newMenuName] as ToolStripMenuItem;

                        if (attrib.MenuItemsProvider == null)
                        {
                            //Add the command if corresponds.
                            if (idx == (menuItems.Length - 1) && //In the last item, create the command.
                                (!string.IsNullOrEmpty(attrib.CommandName))) //There is a command name.
                            {
                                AddCommandInvoker(attrib, menuItem);
                            }
                        }
                        else
                        {
                            //Get the child menu items
                            ProcessChildMenuItemAttribute(menuItem, attrib, modelItem);
                            if (!menuItem.HasDropDownItems)
                            {
                                parent.DropDownItems.Remove(menuItem);
                            }
                        }
                    }
                    else
                    {
                        //Create a new item.
                        if (modelItem != null && modelItem.Length > 1 && attrib.MultipleSelectionMenuItemName != null &&
                            attrib.MultipleSelectionMenuItemName.Length > 0)
                        {
                            newMenuName = attrib.MultipleSelectionMenuItemName;
                        }

                        GuidanceTypeMenuItemAttribute guidanceTypeAtt = attrib as GuidanceTypeMenuItemAttribute;
                        LinkMenuItemAttribute linkAtt = attrib as LinkMenuItemAttribute;
                        if (guidanceTypeAtt != null)
                        {
                            guidanceTypeAtt.ProcessMenuItemName(modelItem != null ? modelItem[0] : null);
                            newMenuName = guidanceTypeAtt.MenuItemName.Substring(guidanceTypeAtt.MenuItemName.LastIndexOf("\\") + 1, guidanceTypeAtt.MenuItemName.Length - guidanceTypeAtt.MenuItemName.LastIndexOf("\\") - 1);
                        }

                        ToolStripMenuItem childItem = new ToolStripMenuItem(newMenuName);
                        ToolStripMenuItem parent = menuItem;
                        childItem.Name = newMenuName;
                        childItem.ShortcutKeys = attrib.ShortCutKeys;

                        if (linkAtt != null)
                        {
                            childItem.Alignment = linkAtt.Alignment;
                            childItem.ForeColor = linkAtt.ForeColor;
                            childItem.Font = linkAtt.TextFont;
                        }

                        menuItem.DropDownItems.Add(childItem);
                        menuItem = childItem;

                        if (attrib.MenuItemsProvider == null)
                        {
                            if (idx == (menuItems.Length - 1) && //In the last item, create the command.
                                (!string.IsNullOrEmpty(attrib.CommandName))) //There is a command name.
                            {
                                AddCommandInvoker(attrib, menuItem);
                            }
                        }
                        else
                        {
                            ProcessChildMenuItemAttribute(menuItem, attrib, modelItem);
                            if (!menuItem.HasDropDownItems)
                            {
                                parent.DropDownItems.Remove(menuItem);
                            }
                            else if (guidanceTypeAtt != null)
                            {
                                parent.DropDownItems.Remove(menuItem);
                                parent.DropDownItems.AddRange(menuItem.DropDownItems);
                            }
                        }
                    }
                } //for (int idx = 0; idx < menuItems.Length; idx++)
            } //foreach (MenuItemAttribute attrib in sortedList.Values)

            return rootMenus;
        }

        /// <summary>
        /// Compute the menu items for the provided root menu item.
        /// </summary>
        private void PopulateRootMenu(ToolStripDropDownItem firstRootMenu)
        {
            //Add menu items for the current node selected in the view.
            TreeNode treeNode = _treeView.LastSelectedNode;
            if (treeNode == null)
            {
                return;
            }

            MenuItemAttribute[] attributes = (MenuItemAttribute[])treeNode.GetType().GetCustomAttributes(typeof(MenuItemAttribute), false);
            List<ToolStripMenuItem> treeNodeRoots = CreateRootMenues(attributes, new IModelItem[] { treeNode as IModelItem }); //TODO: check this. TreeNode should not be a modelItem

            //Update the menu.
            firstRootMenu.DropDown.Items.Clear();

            foreach (ToolStripMenuItem menuItem in treeNodeRoots)
            {
                if (menuItem.Text == firstRootMenu.Text)
                {
                    List<ToolStripItem> subMenus = new List<ToolStripItem>();
                    foreach (ToolStripItem childItem in menuItem.DropDown.Items)
                    {
                        subMenus.Add(childItem);
                    }
                    firstRootMenu.DropDown.Items.AddRange(subMenus.ToArray());
                    break;
                }
            }
        }

        /// <summary>
        /// Process the child menu items defined in the menu item attribute.
        /// </summary>
        /// <param name="parentMenuItem"></param>
        /// <param name="parentAttribute"></param>
        /// <param name="modelItem"></param>
        private void ProcessChildMenuItemAttribute(ToolStripMenuItem parentMenuItem, MenuItemAttribute parentAttribute, IModelItem[] modelItem)
        {
            IModelItem tempModelItem = (modelItem != null && modelItem.Length != 0) ? modelItem[0] : null;
            //Get the child menu items
            MenuItemAttribute[] childMenuItemAttributes = parentAttribute.MenuItemsProvider.GetSubMenuItems(parentAttribute, tempModelItem);
            foreach (MenuItemAttribute childMenuItemAttribute in childMenuItemAttributes)
            {
                //Split the menu item hierarchy.
                string[] menuItems = childMenuItemAttribute.MenuItemName.Split('\\');

                ToolStripMenuItem menuItem = null;

                //Iterate through each menu item.
                for (int idx = 0; idx < menuItems.Length; idx++)
                {
                    string newMenuName = menuItems[idx];
                    if (menuItem == null)
                    {
                        //Check if there is already a root for this menu.
                        foreach (ToolStripMenuItem tempMenu in parentMenuItem.DropDownItems)
                        {
                            if (tempMenu.Text == newMenuName)
                            {
                                menuItem = tempMenu;
                                break;
                            }
                        }

                        //If the root has not been created
                        if (menuItem == null)
                        {
                            ToolStripMenuItem childItem = new ToolStripMenuItem(newMenuName);
                            childItem.Name = newMenuName;
                            string guidanceItemTypeCommand = childMenuItemAttribute.CommandName;
                            parentMenuItem.DropDownItems.Add(childItem);
                            menuItem = childItem;

                            if (idx == (menuItems.Length - 1) && //In the last item, create the command.
                                (!string.IsNullOrEmpty(childMenuItemAttribute.CommandName))) //There is a command name.
                            {
                                AddCommandInvoker(childMenuItemAttribute, menuItem);
                                childItem.Click += delegate(object sender, EventArgs eventArgs)
                                {
                                    NewGuidanceItem(this, new GuidanceTypeEventArgs(GuidanceType.New(guidanceItemTypeCommand)));
                                };
                            }
                        }
                    }
                    else if (newMenuName == "-")
                    {
                        //If there is a separator, then create it without validating previous existence.
                        menuItem.DropDownItems.Add(new ToolStripSeparator());
                    }
                    else if (menuItem.DropDownItems[newMenuName] != null)
                    {
                        //Check if there is already a menu with this name.
                        menuItem = menuItem.DropDownItems[newMenuName] as ToolStripMenuItem;

                        //Add the command if corresponds.
                        if (idx == (menuItems.Length - 1) && //In the last item, create the command.
                            (!string.IsNullOrEmpty(childMenuItemAttribute.CommandName))) //There is a command name.
                        {
                            AddCommandInvoker(childMenuItemAttribute, menuItem);
                        }
                    }
                    else
                    {
                        //Create a new item.
                        ToolStripMenuItem childItem = new ToolStripMenuItem(newMenuName);
                        childItem.Name = newMenuName;
                        string guidanceItemTypeCommand = childMenuItemAttribute.CommandName;
                        menuItem.DropDownItems.Add(childItem);
                        menuItem = childItem;

                        if (idx == (menuItems.Length - 1) && //In the last item, create the command.
                            (!string.IsNullOrEmpty(childMenuItemAttribute.CommandName))) //There is a command name.
                        {
                            childItem.Click += delegate(object sender, EventArgs eventArgs)
                            {
                                NewGuidanceItem(this, new GuidanceTypeEventArgs(GuidanceType.New(guidanceItemTypeCommand)));
                            };
                            AddCommandInvoker(childMenuItemAttribute, menuItem);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Add a command to the workitem.
        /// </summary>
        private void AddCommandInvoker(MenuItemAttribute attrib, ToolStripMenuItem menuItem)
        {
            if (_handlers.ContainsKey(attrib.CommandName))
            {
                menuItem.Click += new EventHandler(_handlers[attrib.CommandName]);
            }
        }

        public void DisplayGuidanceExplorer()
        {
            EnvDTE80.Windows2 wins2obj = (Windows2)VisualStudio.Windows;
            _addInInstance.DTE.StatusBar.Text = "Loading Guidance Explorer AddIn...";
            _addInInstance.DTE.StatusBar.Animate(true, vsStatusAnimation.vsStatusAnimationGeneral);

            try
            {
                Window currentWindow = wins2obj.Item(TreeViewGuid);
                currentWindow.SetFocus();
            }
            catch
            {
                // Create tool window
                object ctlobj = null;
                string classname = "GuidanceExplorerAddIn.Windows.GEWindow";
                string caption = "Guidance Explorer";

                // Create the new tool window and insert the user control in it.
                Window2 guidanceExplorerWin = (Window2)wins2obj.CreateToolWindow2(_addInInstance, this.GetType().Assembly.Location, 
					classname, caption, TreeViewGuid, ref ctlobj);

                //Bitmap bitmap = Resources.MainIcon.ToBitmap();
                //guidanceExplorerWin.SetTabPicture(bitmap.GetHbitmap());

                guidanceExplorerWin.Visible = true;
                if (!guidanceExplorerWin.Linkable)
                {
                    guidanceExplorerWin.Linkable = true;
                }
                if (guidanceExplorerWin.IsFloating)
                {
                    guidanceExplorerWin.IsFloating = false;
                    
                }

                ////------- Dock with Solution Explorer
                //try
                //{
                //    Window2 solutionExplorer = (Window2)wins2obj.Item(EnvDTE.Constants.vsWindowKindSolutionExplorer);
                //    solutionExplorer.Visible = true;
                //    solutionExplorer.Activate();
                //    //Window2 properties = (Window2)_applicationObject.Windows.Item(Constants.vsWindowKindProperties);
                //    //properties.Visible = true;
                //    //properties.Activate();
                //    // solutionExplorer.LinkedWindows.Add(guidanceExplorerWin);
                //    Window2 frame = (Window2)wins2obj.CreateLinkedWindowFrame(solutionExplorer, guidanceExplorerWin, vsLinkedWindowType.vsLinkedWindowTypeTabbed);
                //    IVsWindowFrame frame2 = frame.Object as IVsWindowFrame;


                //        //frame.LinkedWindows.Add(properties);
                //    //frame.LinkedWindows.Item(1).LinkedWindowFrame.Activate();
                //    //frame.sWindowState=vsWindowState.(vsWindowType.((int)__VSFPROPID.VSFPROPID_FrameMode, VSFRAMEMODE.VSFM_MdiChild);

                //}
                //catch (Exception ex)
                //{
                //    System.Diagnostics.Debug.WriteLine(ex.ToString());
                //}
            
                //----------------------------------
                guidanceExplorerWin.SetFocus();

                // Initialize TreeView
                GEWindow geWindow = (GEWindow)ctlobj;
                _treeView = geWindow.TreeView;
                _treeView.ModelService = _modelService;
                //_treeView.SolutionService = _solutionStorageService;
                _treeView.Init();
                // Subscribe Visual Studio events
                _solutionEvents.Opened += new _dispSolutionEvents_OpenedEventHandler(VisualStudio_Solution_Opened);
                _solutionEvents.BeforeClosing += new _dispSolutionEvents_BeforeClosingEventHandler(VisualStudio_Solution_BeforeClosing);
				// If there's an open solution, call the solution opened handler
                if (VisualStudio.Solution.IsOpen)
                {
                    VisualStudio_Solution_Opened();
                }

				// Subscribe TreeView events
                _treeView.LibraryNodeSelected += new EventHandler<GuidanceExplorer.Views.ModelNodeEventArgs<GuidanceExplorer.Model.Library>>(LibraryNodeSelected);
                _treeView.LibrariesNodeSelected += new EventHandler<EventArgs>(LibrariesNodeSelected);
                _treeView.FolderNodeSelected += new EventHandler<GuidanceExplorer.Views.ModelNodeEventArgs<GuidanceExplorer.Model.Folder>>(FolderNodeSelected);
                _treeView.MyViewsSelected += new EventHandler<GuidanceExplorer.Views.ModelNodeEventArgs<GuidanceExplorer.Model.UserViews>>(MyViewsSelected);
                _treeView.ViewNodeSelected += new EventHandler<GuidanceExplorer.Views.ModelNodeEventArgs<GuidanceExplorer.Model.View>>(ViewNodeSelected);
                _treeView.SearchViewNodeSelected += new EventHandler<ModelNodeEventArgs<SearchView>>(SearchViewNodeSelected);
                _treeView.GuidanceTypeNodeSelected += new EventHandler<GuidanceExplorer.Views.ModelNodeEventArgs<GuidanceExplorer.Model.GuidanceType>>(GuidanceTypeNodeSelected);
                _treeView.OpeningContextMenuTreeView += new EventHandler<System.ComponentModel.CancelEventArgs>(OpeningContextMenuTreeView);
                _treeView.DropFolderToUserViews += new EventHandler<DropOperationEventArgs<Folder, UserViews>>(DropFolderToUserViews);
                _treeView.ChecklistNodeSelected += new EventHandler<ModelNodeEventArgs<GuidanceExplorer.Model.Checklist>>(ChecklistNodeSelected);
                _treeView.GuidanceItemNodeSelected += new EventHandler<GuidanceItemFileReferenceEventArgs>(GuidanceItemOpened);
                //_treeView.GuidanceItemNodeSelected += new EventHandler<ModelNodeEventArgs<GuidanceItemFileReference>>(_treeView_GuidanceItemNodeSelected);
                _treeView.DropItemToView += new EventHandler<ItemDropOperationEventArgs<GuidanceItemFileReference, GuidanceExplorer.Model.View>>(DropItemToView);
                _treeView.DropItemToChecklist += new EventHandler<ItemDropOperationEventArgs<GuidanceItemFileReference, Checklist>>(DropItemToChecklist);
				_treeView.DropViewToFolder += new EventHandler<DropOperationEventArgs<GuidanceExplorer.Model.View, Folder>>(DropViewToFolder);
				_treeView.DropFolderToFolder += new EventHandler<DropOperationEventArgs<Folder, Folder>>(DropFolderToFolder);
				_treeView.DropCheckListToFolder += new EventHandler<DropOperationEventArgs<Checklist, Folder>>(DropCheckListToFolder);
				_treeView.DropFolderToSolutionNode += new EventHandler<DropOperationEventArgs<Folder, SolutionViews>>(DropFolderToSolutionNode);
				_treeView.DropCheckListToSolutionNode += new EventHandler<DropOperationEventArgs<Checklist, SolutionViews>>(DropCheckListToSolutionNode);
				_treeView.DropViewToSolutionNode += new EventHandler<DropOperationEventArgs<GuidanceExplorer.Model.View, SolutionViews>>(DropViewToSolutionNode);
				_treeView.DropSearchViewToFolder += new EventHandler<DropOperationEventArgs<SearchView, Folder>>(DropSearchViewToFolder);
                _treeView.DropViewToLibrary += new EventHandler<DropOperationEventArgs<GuidanceExplorer.Model.View, Library>>(DropViewToLibrary);
                _treeView.DropViewToUserViews += new EventHandler<DropOperationEventArgs<GuidanceExplorer.Model.View, UserViews>>(DropViewToUserViews);
                _treeView.DropSearchViewToLibrary += new EventHandler<DropOperationEventArgs<SearchView, Library>>(DropSearchViewToLibrary);
				_treeView.DropSearchViewToUserViews += new EventHandler<DropOperationEventArgs<SearchView, UserViews>>(DropSearchViewToUserViews);
				_treeView.DropFolderToLibrary += new EventHandler<DropOperationEventArgs<Folder, Library>>(DropFolderToLibrary);
				_treeView.DropViewToChecklist += new EventHandler<DropOperationEventArgs<GuidanceExplorer.Model.View, Checklist>>(DropViewToChecklist);
				_treeView.DropFolderToCheckList += new EventHandler<DropOperationEventArgs<Folder, Checklist>>(DropFolderToCheckList);
				_treeView.DropSearchViewToCheckList += new EventHandler<DropOperationEventArgs<SearchView, Checklist>>(DropSearchViewToCheckList);
				_treeView.DropViewToView += new EventHandler<DropOperationEventArgs<GuidanceExplorer.Model.View, GuidanceExplorer.Model.View>>(DropViewToView);
				_treeView.DropSearchViewToView += new EventHandler<DropOperationEventArgs<SearchView, GuidanceExplorer.Model.View>>(DropSearchViewToView);
				_treeView.DropFolderToView += new EventHandler<DropOperationEventArgs<Folder, GuidanceExplorer.Model.View>>(DropFolderToView);
			
            }

            _addInInstance.DTE.StatusBar.Text = "Ready";
            _addInInstance.DTE.StatusBar.Animate(false, vsStatusAnimation.vsStatusAnimationGeneral);
        }

        // <summary>
        /// Gets the model node that contains the provided model instance
        /// </summary>
        public ModelNode<T> GetNodeByModelInstance<T>(T modelInstance)
            where T : ILibraryNodes
        {
            if (modelInstance.ParentFolder == null)
            {
                // Search in MyViews
                MyViewsNode myViews = GetMyViewsNode();
                if (myViews != null)
                {
                    foreach (TreeNode node in myViews.Nodes)
                    {
                        IModelItem modelNode = node as IModelItem;
                        if (modelNode != null)
                        {
                            ModelNode<T> tNode = modelNode as ModelNode<T>;
                            if (tNode != null && tNode.ModelInstance.Equals(modelInstance))
                            {
                                return tNode;
                            }
                        }
                    }
                }

                // It wasn't found, search in Solution node
                SolutionNode solutionNode = _winFormsRenderService.GetSolutionNode(_treeView.TreeView);
                if (solutionNode != null)
                {
                    foreach (TreeNode folder_node in solutionNode.Nodes)
                    {
                        IModelItem modelNode = folder_node as IModelItem;
                        if (modelNode != null)
                        {
                            ModelNode<T> tNode = modelNode as ModelNode<T>;
                            if (tNode != null && tNode.ModelInstance.Equals(modelInstance))
                            {
                                return tNode;
                            }
                        }
                    }
                }
            }
            else
            {
                ModelNode<Folder> parentNode = GetNodeByModelInstance<Folder>(modelInstance.ParentFolder);
                foreach (TreeNode node in parentNode.Nodes)
                {
                    IModelItem modelNode = node as IModelItem;
                    if (modelNode != null)
                    {
                        ModelNode<T> tNode = modelNode as ModelNode<T>;
                        if (tNode != null && tNode.ModelInstance.Equals(modelInstance))
                        {
                            return tNode;
                        }
                    }
                }
            }

            return null;
        }

        /// <summary>
        /// Return the MyViews node
        /// </summary>
        private MyViewsNode GetMyViewsNode()
        {
            foreach (TreeNode node in _treeView.TreeView.Nodes)
            {
                MyViewsNode myViews = node as MyViewsNode;
                if (myViews != null)
                {
                    return myViews;
                }
            }

            return null;
        }

        /// <summary>
        /// Enum for Controls Types.
        /// </summary>		
        public enum ControlsType
        {
            View,
            Folder,
            CheckList
        }

        /// <summary>
        /// Returns the default name for a new control at the specified parent node
        /// </summary>
        static public string GetNewDefaultName(TreeNode parent, ControlsType control)
        {
            // Build texts list
            List<String> texts = new List<string>();
            foreach (TreeNode node in parent.Nodes)
            {
                texts.Add(node.Text);
            }

            // Look for a not used text
            int i = 0;
            string ret = "";
            do
            {
                ++i;
                switch (control)
                {
                    case ControlsType.CheckList:
                        ret = "CheckList " + i;
                        break;
                    case ControlsType.Folder:
                        ret = "Folder " + i;
                        break;
                    case ControlsType.View:
                        ret = "View " + i;
                        break;
                }
            }
            while (texts.Contains(ret));

            return ret;
        }

        /// <summary>
        /// What to do when a generic exception is thrown
        /// </summary>
        public void HandleException(Exception ex)
        {
            MessageBox.Show(ex.ToString(),"Guidance Explorer Add-In Error",MessageBoxButtons.OK,MessageBoxIcon.Error);
        }

        /// <summary>
        /// Return the currently selected library.
        /// </summary>
        /// <returns></returns>
        private Library GetCurrentLibrary()
        {
            Library library = null;
            TreeNode currentTreeNode = _treeView.GetCurrentNode();
            IModelItem modelItem = currentTreeNode as IModelItem;
            if (modelItem == null)
            {
                //Library can be only detected from a model item.
                return library;
            }

            LibraryNode libraryNode = modelItem as LibraryNode;
            FolderNode folderNode = modelItem as FolderNode;
            ViewNode viewNode = modelItem as ViewNode;
            GuidanceTypeNode guidanceTypeNode = modelItem as GuidanceTypeNode;
            if (libraryNode != null)
            {
                library = libraryNode.ModelInstance;
            }
            else if (folderNode != null)
            {
                library = folderNode.ModelInstance.GetContainerLibrary();
            }
            else if (viewNode != null)
            {
                library = viewNode.ModelInstance.GetContainerLibrary();
            }
            else if (guidanceTypeNode != null)
            {
                libraryNode = guidanceTypeNode.Parent as LibraryNode;
                library = libraryNode.ModelInstance;
            }
            else
            {
                //Unknown IModelItem
                return null;
            }
            return library;
        }
        /// <summary>
        /// Selects the given node
        /// </summary>
        /// <param name="node"></param>
        private void SelectNode(TreeNode node)
        {
            _treeView.SelectedNodes.Clear();
            _treeView.SelectedNodes.Add(node);
        }

        private void AddNodeToSelection(TreeNode node)
        {
            _treeView.SelectedNodes.Add(node);
        }

        private void CleanNodeSelection()
        {
            _treeView.SelectedNodes.Clear();
        }

        private bool LoadAddinGuidance(EnvDTE.Solution solution)
        {
            if (solution != null && !String.IsNullOrEmpty(solution.FullName))
            {
                string solutionName = (string)solution.Properties.Item("Name").Value;
                _modelService.LoadSolutionGuidance(solutionName, solution.FullName);
                return true;
            }
            return false;
        }

    }
}
